﻿using KBEngine.Setting;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace KBEngineTool.UI
{
    public partial class KBESettings : Form
    {
        KBEngineDefaults _kbeSetting = new KBEngineDefaults();
        public KBESettings()
        {
            InitializeComponent();
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            _kbeSetting = XmlSerializeOpt.ReadKBESetting(SlnConfig.Inst.defaultSettingXML, SlnConfig.Inst.settingXML);
            AutoCreater();
            //treeView1.ExpandAll();
            treeView1.AfterSelect += TreeView1_AfterSelect;
        }


        private void Btn_Confirm_Click(object sender, EventArgs e)
        {
            XmlSerializeOpt.WriteKBESetting(SlnConfig.Inst.settingXML, _kbeSetting, SlnConfig.Inst.defaultSettingXML);
        }
        private void Btn_Cancel_Click(object sender, EventArgs e)
        {
        }

        private void TreeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            var treeView = (TreeView)sender;
            if (treeView.SelectedNode.Tag == null)
                return;

            var serObj = treeView.SelectedNode.Tag;

            //自动创建控件
            var type = serObj.GetType();
            var fileInfoArray = type.GetFields();
            m_flowLayout.Controls.Clear();
            foreach (var fileInfo in fileInfoArray)
            {
                if (fileInfo.FieldType.IsPrimitive || fileInfo.FieldType == typeof(string))
                {
                    var flowLayout2 = new FlowLayoutPanel();
                    flowLayout2.AutoSize = true;

                    var controlLab = new Label();
                    controlLab.Text = $"{fileInfo.Name}({fileInfo.FieldType.Name})";
                    controlLab.Dock = DockStyle.Left;
                    controlLab.TextAlign = ContentAlignment.MiddleCenter;
                    controlLab.AutoSize = true;
                    flowLayout2.Controls.Add(controlLab);

                    var control = new TextBox();
                    control.Text = fileInfo.GetValue(serObj).ToString();
                    control.AutoSize = true;
                    control.Tag = new object[] { serObj, fileInfo };
                    control.TextChanged += Control_TextChanged;
                    flowLayout2.Controls.Add(control);

                    m_flowLayout.Controls.Add(flowLayout2);
                }
            }
        }
        private void Control_TextChanged(object sender, EventArgs e)
        {
            var control = sender as Control;
            var objArray = control.Tag as object[];
            if (objArray == null)
                return;
            var fileInfo = (FieldInfo)objArray[1];
            TypeConverter converter = TypeDescriptor.GetConverter(fileInfo.FieldType);
            object newVal;
            try
            {
                newVal = converter.ConvertFromString(control.Text);
            }
            catch (Exception)
            {
                newVal = Activator.CreateInstance(fileInfo.FieldType);
            }
            fileInfo.SetValue(objArray[0], newVal);
        }


        private void AutoCreater()
        {
            var tabs = new string[] {"interfaces", "dbmgr", "cellapp", "baseApp", "cellappmgr", "baseappmgr", "loginapp", "machine", "bots", "logger" };
            var fileInfoArray = typeof(KBEngineDefaults).GetFields();
            treeView1.Nodes.Clear();

            var globalNode = treeView1.Nodes.Add("global");
            globalNode.Tag = _kbeSetting;
            var tempNode = globalNode;
            foreach (var fieldInfo in fileInfoArray)
            {
                tempNode = globalNode;
                if (Array.Exists(tabs, fieldInfo.Name.Equals))
                {
                    var tempNodes = treeView1.Nodes.Find(fieldInfo.Name, false);
                    tempNode = tempNodes.Length < 1 ? treeView1.Nodes.Add(fieldInfo.Name) : tempNodes[0];
                    var childObj = fieldInfo.GetValue(_kbeSetting);
                    if (childObj == null)
                    { 
                        childObj = Activator.CreateInstance(fieldInfo.FieldType);
                        fieldInfo.SetValue(_kbeSetting, childObj);
                    }
                    tempNode.Tag = childObj;
                    _AutoCreator(tempNode, childObj);
                    continue;
                }
                else
                {
                    if (_IsClass(fieldInfo.FieldType))
                    {
                        tempNode = tempNode.Nodes.Add(fieldInfo.Name);
                        var childObj = fieldInfo.GetValue(_kbeSetting);
                        if (childObj == null)
                        { 
                            childObj = Activator.CreateInstance(fieldInfo.FieldType);
                            fieldInfo.SetValue(_kbeSetting, childObj);
                        }
                        tempNode.Tag = childObj;
                        _AutoCreator(tempNode, childObj);
                    }
                    else
                    {
                        tempNode = globalNode;
                    }
                }
            }
        }
        private bool _IsClass(System.Type type)
        {
            return !type.IsGenericType && !type.IsPrimitive && type.IsClass && type != typeof(string);
        }
        private void _AutoCreator(TreeNode parentNode, object obj)
        {
            var type = obj.GetType();
            var fileInfoArray = type.GetFields();
            var tempNode = parentNode;
            foreach (var fieldInfo in fileInfoArray)
            {
                if (_IsClass(fieldInfo.FieldType))
                {
                    tempNode = tempNode.Nodes.Add(fieldInfo.Name);
                    var childObj = fieldInfo.GetValue(obj);
                    if (childObj == null)
                    { 
                        childObj = Activator.CreateInstance(fieldInfo.FieldType);
                        fieldInfo.SetValue(obj, childObj);
                    }
                    tempNode.Tag = childObj;
                    _AutoCreator(tempNode, childObj);
                }
                else
                {
                    tempNode = parentNode;
                }
            }
        }
    }
}
